/*******************************************************************************
 * Copyright 2011 See AUTHORS file.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *   http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 ******************************************************************************/
package com.badlogicgames.superjumper;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.math.Vector2;

public class World {
    public interface WorldListener {
        public void jump();

        public void highJump();

        public void hit();

        public void coin();
    }

    public static final float WORLD_WIDTH = Settings.WORLD_WIDTH;
    public static final float WORLD_HEIGHT = Settings.WORLD_HEIGHT;
    public static final int WORLD_STATE_RUNNING = 0;
    public static final int WORLD_STATE_NEXT_LEVEL = 1;
    public static final int WORLD_STATE_GAME_OVER = 2;
    public static final Vector2 gravity = new Vector2(0, 10);
//    private double touchIncrement=0;

    public final Pigeon bob;
    public final List<Platform> platforms;
    public final List<Spring> springs;
    public final List<Squirrel> squirrels;
    public final List<Coin> coins;
    public final List<Turret> turrets;
    public Castle castle;
    public List <Floor> floors;
    public final WorldListener listener;
    public final Random rand;

    public float widthSoFar;
    public int score;
    public int completedSoFar;
    public int state;

    public World(WorldListener listener) {
        this.bob = new Pigeon(Settings.FRUSTUM_WIDTH/2, Settings.FRUSTUM_HEIGHT/2);  //bob start in centre of screen.
        this.platforms = new ArrayList<Platform>();
        this.springs = new ArrayList<Spring>();
        this.squirrels = new ArrayList<Squirrel>();
        this.coins = new ArrayList<Coin>();
        this.turrets = new ArrayList<Turret>();
        this.floors = new ArrayList<Floor>();
        this.listener = listener;
        rand = new Random();
        generateLevel();

        this.widthSoFar = 0;
        this.score = 0;
        this.completedSoFar = 0;
        this.state = WORLD_STATE_RUNNING;
    }

    private void generateLevel() {
        float x = 0;
        float y=0;
        Platform platform1 = new Platform(Platform.PLATFORM_TYPE_STATIC, x, y);
        platforms.add(platform1);  // first item
        
        
  //      float maxJumpHeight = Pigeon.BOB_JUMP_VELOCITY * Pigeon.BOB_JUMP_VELOCITY / (2 * -gravity.x);
        while (x < WORLD_WIDTH) {
            x+=rand.nextInt(10);    /// random for next item
            y = rand.nextFloat()
                    * (WORLD_HEIGHT);
            
        	int type = rand.nextFloat() > 0.8f ? Platform.PLATFORM_TYPE_MOVING
                    : Platform.PLATFORM_TYPE_STATIC;
            

             if (rand.nextFloat() > 0.6f) {
            Platform platform = new Platform(type, x, y);
            platforms.add(platform);
             }

            if (rand.nextFloat() > 0.6f) {
                Squirrel squirrel = new Squirrel(x + rand.nextFloat(), 
                        y,
                        this.bob);
                squirrels.add(squirrel);
            }

            if (rand.nextFloat() > 0.6f) {
                Coin coin = new Coin(x, y);
                coins.add(coin);
            }

            if (rand.nextFloat() > 0.6f) {

            Turret turret = new Turret(x, Settings.GROUND_POSITION);
//          + rand.nextFloat() * 3);
            turrets.add(turret);
            }
            
            float floorX = 0f, floorY = 0f;
            for(int i=0; i< WORLD_WIDTH/Floor.FLOOR_WIDTH+1;i++){
            	floorX = i * Floor.FLOOR_WIDTH;
            	Floor floor = new Floor(floorX, floorY);
            	floors.add(floor);
            }
            
            
          }
  
        
        
        
        castle = new Castle(x, 5);
        
    }
    public void update(float deltaTime, float accelX, float accelY, boolean isTouched) {
        updateBob(deltaTime, accelX, accelY, isTouched);
        updatePlatforms(deltaTime);
        updateSquirrels(deltaTime);
        updateCoins(deltaTime);
        updateTurrets(deltaTime);
        if (bob.state != Pigeon.BOB_STATE_DIED){ checkCollisions(); }
        checkGameOver();
    }

    /**
     * updateBob if isTouched the velocity of x is opposes the gravity.*/
    private void updateBob(float deltaTime, float accelX, float accelY, boolean isTouched ) {
        bob.update(deltaTime, accelX, accelY,  isTouched);
        widthSoFar = Math.max(bob.position.x, widthSoFar);
        this.completedSoFar = (int)widthSoFar/(int)World.WORLD_WIDTH*100;
    }

    private void updatePlatforms(float deltaTime) {
        int len = platforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = platforms.get(i);
            platform.update(deltaTime);
            if (platform.state == Platform.PLATFORM_STATE_PULVERIZING
                    && platform.stateTime > Platform.PLATFORM_PULVERIZE_TIME) {
                platforms.remove(platform);
                len = platforms.size();
            }
        }
    }

    private void updateSquirrels(float deltaTime) {
        int len = squirrels.size();
        for (int i = 0; i < len; i++) {
            Squirrel squirrel = squirrels.get(i);
            squirrel.update(deltaTime);
        }
    }

    private void updateCoins(float deltaTime) {
        int len = coins.size();
        for (int i = 0; i < len; i++) {
            Coin coin = coins.get(i);
            coin.update(deltaTime);
        }
    }
    
    private void updateTurrets(float deltaTime) {
        int len = turrets.size();
        for (int i = 0; i < len; i++) {
            Turret turret = turrets.get(i);
            turret.update(deltaTime);
        }
    }

    private void checkCollisions() {
        checkPlatformCollisions();
        checkGroundCollisions();
        checkSquirrelCollisions();
        checkItemCollisions();
        checkCastleCollisions();
    }

    private void checkGroundCollisions() {
    	for(Floor floor:this.floors){
    		if (OverlapTester.overlapRectangles(floor.bounds, bob.bounds)) {
                bob.position.y = floor.bounds.getHeight()+1/32;
            }	
    	}
    	 
    }
    
    
    private void checkPlatformCollisions() {

        int len = platforms.size();
        for (int i = 0; i < len; i++) {
            Platform platform = platforms.get(i);
   //         if (bob.position.y > platform.position.y) {
            
            
                if (OverlapTester
                        .overlapRectangles(bob.bounds, platform.bounds)) {
                    bob.hitPlatform();
                    listener.jump();
                    if (rand.nextFloat() > 0.5f) {
                        platform.pulverize();
                    }
                    break;
                }
    //        }
        }
    }

    private void checkSquirrelCollisions() {
        int len = squirrels.size();
        for (int i = 0; i < len; i++) {
            Squirrel squirrel = squirrels.get(i);
            if (OverlapTester.overlapRectangles(squirrel.bounds, bob.bounds)) {
                bob.hitSquirrel(squirrel.velocity);
                listener.hit();
            }
        }
    }

    private void checkItemCollisions() {
        int len = coins.size();
        for (int i = 0; i < len; i++) {
            Coin coin = coins.get(i);
            if (OverlapTester.overlapRectangles(bob.bounds, coin.bounds)) {
                coins.remove(coin);
                
                len = coins.size();
                listener.coin();
                score += Coin.COIN_SCORE;
                Pigeon.stamina+=100;
            }

        }

       
        


        len = springs.size();
        for (int i = 0; i < len; i++) {
            Spring spring = springs.get(i);
        //    if (bob.position.y > spring.position.y) {
                if (OverlapTester.overlapRectangles(bob.bounds, spring.bounds)) {
                    bob.hitSpring();
                    listener.highJump();
                }
          //  }
        }
    }

    private void checkCastleCollisions() {
        if (OverlapTester.overlapRectangles(castle.bounds, bob.bounds)) {
            state = WORLD_STATE_NEXT_LEVEL;
        }
    }

    private void checkGameOver() {
//		if (widthSoFar - 7.5f > bob.position.y) {
//		if (WORLD_WIDTH+1 <= bob.position.x || -1 >= bob.position.y) {
			if (bob.state == Pigeon.BOB_STATE_DIED) {
               state = WORLD_STATE_GAME_OVER;
        }
    }
}
